// 类型定义 - 基于现有八字系统的数据结构
interface BaziSystemHiddenStem {
    stem: string;
    tenStar: string;
    type: string;
    wuxing: string;
  }

interface PatternHiddenStem {
    stem: string;
    relation: string;
    strength: string;
    is_exposed: boolean;
    exposed_pillar: string | null;
  }
  
  interface MonthBranchAnalysis {
    branch: string;
    hidden_stems: PatternHiddenStem[];
    month_stem?: string; // 月干信息
  }
  
  interface BaziData {
    year_pillar: string;
    month_pillar: string;
    day_pillar: string;
    hour_pillar: string;
  }
  
  interface DayMaster {
    heavenly_stem: string;
  }
  
  interface BaziInput {
    bazi_data: BaziData;
    day_master: DayMaster;
    month_branch_analysis: MonthBranchAnalysis;
  }

  // 从现有八字系统数据转换的接口
  interface BaziSystemData {
    year: {
      stem: string;
      branch: string;
      tenStar: string;
      zanggan: BaziSystemHiddenStem[];
    };
    month: {
      stem: string;
      branch: string;
      tenStar: string;
      zanggan: BaziSystemHiddenStem[];
    };
    day: {
      stem: string;
      branch: string;
      tenStar: string;
      zanggan: BaziSystemHiddenStem[];
    };
    hour: {
      stem: string;
      branch: string;
      tenStar: string;
      zanggan: BaziSystemHiddenStem[];
    };
  }
  
  // 格局名称映射
  const PATTERN_NAMES: Record<string, string> = {
    '正官': '正官格',
    '七杀': '七杀格', 
    '正财': '正财格',
    '偏财': '偏财格',
    '正印': '正印格',
    '偏印': '偏印格',
    '食神': '食神格',
    '伤官': '伤官格',
    '比肩': '比肩格',
    '劫财': '劫财格'
  };

  // 日元旺衰状态常量（7级分类，参考传统八字理论）
  const DAY_MASTER_STRENGTH = {
    JI_WANG: '极旺',     // 得令 + 得地 + 得势（特别强）
    SHEN_QIANG: '身强',   // 得令 + 得地 + 得势
    PIAN_QIANG: '偏强',   // 得令 + (得地或得势其一)
    PING_HE: '平和',      // 得令但不得地不得势，或不得令但得地且得势
    PIAN_RUO: '偏弱',     // 不得令 + (得地或得势其一)
    SHEN_RUO: '身弱',     // 不得令 + 不得地 + 不得势
    JI_RUO: '极弱'        // 不得令 + 不得地 + 不得势（特别弱）
  } as const;
  

  // 三合局配置
  const SANHE_PATTERNS = {
    '寅午戌': { name: '火局', pattern: '炎上格' },
    '申子辰': { name: '水局', pattern: '润下格' },
    '巳酉丑': { name: '金局', pattern: '从革格' },
    '亥卯未': { name: '木局', pattern: '曲直格' }
  };

  // 三会局配置
  const SANHUI_PATTERNS = {
    '寅卯辰': { name: '木局', pattern: '曲直格' },
    '巳午未': { name: '火局', pattern: '炎上格' },
    '申酉戌': { name: '金局', pattern: '从革格' },
    '亥子丑': { name: '水局', pattern: '润下格' }
  };
  
  class PatternAnalyzer {
    // 从现有八字系统数据转换为格局分析所需格式
    private convertBaziSystemData(baziData: BaziSystemData): BaziInput {
      const dayMaster = baziData.day.stem;
      const monthBranch = baziData.month.branch;
      
      // 转换藏干数据格式，直接使用已有的数据
      const hiddenStems: PatternHiddenStem[] = baziData.month.zanggan.map(zanggan => ({
        stem: zanggan.stem,
        relation: zanggan.tenStar,
        strength: zanggan.type,
        is_exposed: this.checkIfExposed(zanggan.stem, baziData),
        exposed_pillar: this.getExposedPillar(zanggan.stem, baziData)
      }));
      
      return {
        bazi_data: {
          year_pillar: baziData.year.stem + baziData.year.branch,
          month_pillar: baziData.month.stem + baziData.month.branch,
          day_pillar: baziData.day.stem + baziData.day.branch,
          hour_pillar: baziData.hour.stem + baziData.hour.branch
        },
        day_master: {
          heavenly_stem: dayMaster
        },
        month_branch_analysis: {
          branch: monthBranch,
          hidden_stems: hiddenStems,
          month_stem: baziData.month.stem
        }
      };
    }
    
    // 检查藏干是否透出
    private checkIfExposed(stem: string, baziData: BaziSystemData): boolean {
      return baziData.year.stem === stem || 
             baziData.month.stem === stem || 
             baziData.day.stem === stem || 
             baziData.hour.stem === stem;
    }
    
    // 获取透出的柱位
    private getExposedPillar(stem: string, baziData: BaziSystemData): string | null {
      if (baziData.year.stem === stem) return 'year';
      if (baziData.month.stem === stem) return 'month';
      if (baziData.day.stem === stem) return 'day';
      if (baziData.hour.stem === stem) return 'hour';
      return null;
    }

    // 检查三合三会局
    private checkSanheSanhui(baziData: BaziSystemData): { pattern: string; type: string; reasoning: string } | null {
      const branches = [
        baziData.year.branch,
        baziData.month.branch, 
        baziData.day.branch,
        baziData.hour.branch
      ];
      
      // 先检查三合局（优先级更高）
      for (const [pattern, config] of Object.entries(SANHE_PATTERNS)) {
        const patternBranches = pattern.split('');
        if (patternBranches.every(branch => branches.includes(branch))) {
          return {
            pattern: config.pattern,
            type: '三合局',
            reasoning: `地支${pattern}构成三合${config.name}，取${config.pattern}`
          };
        }
      }
      
      // 再检查三会局（需要三个地支齐全，力量更强）
      for (const [pattern, config] of Object.entries(SANHUI_PATTERNS)) {
        const patternBranches = pattern.split('');
        if (patternBranches.every(branch => branches.includes(branch))) {
          return {
            pattern: config.pattern,
            type: '三会局',
            reasoning: `地支${pattern}构成三会${config.name}，取${config.pattern}`
          };
        }
      }
      
      return null;
    }

    // 检查专旺格
    private checkZhuanwangPattern(baziData: BaziSystemData): { pattern: string; reasoning: string } | null {
      const dayMaster = baziData.day.stem;
      const dayMasterWuxing = this.getWuxing(dayMaster);
      const monthBranch = baziData.month.branch;
      const monthWuxing = this.getBranchWuxing(monthBranch);
      
      // 1. 检查日主是否得令（基于月支藏干分析）
      
      // 检查月支藏干中是否有日主同类
      const hasSameWuxingZanggan = baziData.month.zanggan.some(zanggan => 
        this.getWuxing(zanggan.stem) === dayMasterWuxing
      );
      
      // 检查月支五行是否与日主相同或生助日主
      const isDeLing = (dayMasterWuxing === monthWuxing) || 
                      hasSameWuxingZanggan || 
                      this.isShengZhu(monthWuxing, dayMasterWuxing);
      
      if (!isDeLing) {
        return null; // 日主不得令，不构成专旺格
      }
      
      // 2. 检查地支是否成局（三合三会或同类聚集）
      const branches = [
        baziData.year.branch,
        baziData.month.branch,
        baziData.day.branch,
        baziData.hour.branch
      ];
      
      const wuxingBranches = this.getWuxingBranches(dayMasterWuxing);
      const sameWuxingBranchCount = branches.filter(branch => wuxingBranches.includes(branch)).length;
      
      // 3. 检查天干透出情况
      const allStems = [
        baziData.year.stem,
        baziData.month.stem,
        baziData.day.stem,
        baziData.hour.stem
      ];
      
      const sameWuxingStemCount = allStems.filter(stem => this.getWuxing(stem) === dayMasterWuxing).length;
      
      // 4. 检查是否有破格因素（克泄耗）
      const hasBreakFactors = this.checkBreakFactors(baziData, dayMasterWuxing);
      
      // 专旺格条件：日主得令 + 地支成局 + 无破格因素
      // 放宽条件：地支成局（>=2个同类地支）且无破格因素
      if (sameWuxingBranchCount >= 2 && !hasBreakFactors) {
        const patterns = {
          '木': '曲直格',
          '火': '炎上格', 
          '土': '稼穑格',
          '金': '从革格',
          '水': '润下格'
        };
        
        return {
          pattern: patterns[dayMasterWuxing],
          reasoning: `日主${dayMaster}得令于${monthBranch}月，地支${sameWuxingBranchCount}个${dayMasterWuxing}支，无破格因素，构成专旺格${patterns[dayMasterWuxing]}`
        };
      }
      
      return null;
    }

    // 检查从弱格
    private checkCongruoPattern(baziData: BaziSystemData): { pattern: string; reasoning: string } | null {
      const dayMaster = baziData.day.stem;
      const dayMasterWuxing = this.getWuxing(dayMaster);
      const monthBranch = baziData.month.branch;
      const monthWuxing = this.getBranchWuxing(monthBranch);
      
      // 1. 检查日主是否失令（基于得令判断）
      const isDeling = this.checkDeling(baziData);
      if (isDeling) {
        return null; // 日主得令，不构成从弱格
      }
      
      // 2. 检查是否有印比生扶
      const hasYinBiShengFu = this.checkYinBiShengFu(baziData, dayMaster);
      if (hasYinBiShengFu) {
        return null; // 有印比生扶，不构成从弱格
      }
      
      // 3. 检查日主是否无根（地支无同类）
      const branches = [
        baziData.year.branch,
        baziData.month.branch,
        baziData.day.branch,
        baziData.hour.branch
      ];
      const wuxingBranches = this.getWuxingBranches(dayMasterWuxing);
      const hasRoot = branches.some(branch => wuxingBranches.includes(branch));
      if (hasRoot) {
        return null; // 日主有根，不构成从弱格
      }
      
      // 4. 检查地支藏干中是否有日主同类
      const allZanggan = [
        ...baziData.year.zanggan,
        ...baziData.month.zanggan,
        ...baziData.day.zanggan,
        ...baziData.hour.zanggan
      ];
      const hasZangganRoot = allZanggan.some(zanggan => 
        this.getWuxing(zanggan.stem) === dayMasterWuxing
      );
      if (hasZangganRoot) {
        return null; // 地支藏干中有日主同类，不构成从弱格
      }
      
      // 5. 分析从格类型
      const congPattern = this.analyzeCongPattern(baziData, dayMaster);
      if (congPattern) {
        return congPattern;
      }
      
      return null;
    }


    // 检查是否有印比生扶
    private checkYinBiShengFu(baziData: BaziSystemData, dayMaster: string): boolean {
      // 检查天干十神
      const tenStars = [
        baziData.year.tenStar,
        baziData.month.tenStar,
        baziData.hour.tenStar
      ];
      
      // 检查是否有比劫（比肩、劫财）
      const hasBiJie = tenStars.some(tenStar => 
        tenStar === '比肩' || tenStar === '劫财'
      );
      
      // 检查是否有印星（正印、偏印）
      const hasYinXing = tenStars.some(tenStar => 
        tenStar === '正印' || tenStar === '偏印'
      );
      
      // 检查地支藏干中的印比
      const allZanggan = [
        ...baziData.year.zanggan,
        ...baziData.month.zanggan,
        ...baziData.day.zanggan,
        ...baziData.hour.zanggan
      ];
      
      // 检查地支藏干中是否有比劫
      const hasZangganBiJie = allZanggan.some(zanggan => 
        zanggan.tenStar === '比肩' || zanggan.tenStar === '劫财'
      );
      
      // 检查地支藏干中是否有印星
      const hasZangganYinXing = allZanggan.some(zanggan => 
        zanggan.tenStar === '正印' || zanggan.tenStar === '偏印'
      );
      
      return hasBiJie || hasYinXing || hasZangganBiJie || hasZangganYinXing;
    }

    // 分析从格类型
    private analyzeCongPattern(baziData: BaziSystemData, dayMaster: string): { pattern: string; reasoning: string } | null {
      // 直接使用数据中已经计算好的十神关系
      const tenStars = [
        baziData.year.tenStar,
        baziData.month.tenStar,
        baziData.hour.tenStar
      ];
      
      // 统计各十神数量
      const tenStarCount = {
        '正官': 0, '七杀': 0, '正财': 0, '偏财': 0, '食神': 0, '伤官': 0
      };
      
      tenStars.forEach(tenStar => {
        if (tenStarCount.hasOwnProperty(tenStar)) {
          tenStarCount[tenStar]++;
        }
      });
      
      // 找出最多的十神
      const tenStarEntries = Object.entries(tenStarCount);
      if (tenStarEntries.length === 0) {
        return null;
      }
      
      const maxTenStar = tenStarEntries.reduce((a, b) => 
        tenStarCount[a[0]] > tenStarCount[b[0]] ? a : b
      );
      
      // 根据最多的十神确定从格类型（需要至少2个以上才能构成从弱格）
      if (maxTenStar[1] >= 2) {
        const patterns = {
          '正官': '从官格',
          '七杀': '从杀格',
          '正财': '从财格',
          '偏财': '从财格',
          '食神': '从儿格',
          '伤官': '从儿格'
        };
        
        return {
          pattern: patterns[maxTenStar[0]],
          reasoning: `日主${dayMaster}失令无根，${maxTenStar[0]}旺透${maxTenStar[1]}个，构成从弱格${patterns[maxTenStar[0]]}`
        };
      }
      
      return null;
    }

    // 获取天干五行
    private getWuxing(stem: string): string {
      const wuxingMap = {
        '甲': '木', '乙': '木',
        '丙': '火', '丁': '火', 
        '戊': '土', '己': '土',
        '庚': '金', '辛': '金',
        '壬': '水', '癸': '水'
      };
      return wuxingMap[stem] || '';
    }


    

    // 判断是否得令（二元判断，符合传统八字理论）
    private checkDeling(baziData: BaziSystemData): boolean {
      const dayMaster = baziData.day.stem;
      const dayMasterWuxing = this.getWuxing(dayMaster);
      const monthBranch = baziData.month.branch;
      const monthWuxing = this.getBranchWuxing(monthBranch);
      
      // 1. 月支五行与日主相同（直接得令）
      if (dayMasterWuxing === monthWuxing) {
        return true;
      }
      
      // 2. 月支藏干中有日主同类（藏干得令）
      const hasSameWuxingZanggan = baziData.month.zanggan.some(zanggan => 
        zanggan.wuxing === dayMasterWuxing
      );
      if (hasSameWuxingZanggan) {
        return true;
      }
      
      // 3. 月支五行生助日主（印星得令）
      if (this.isShengZhu(monthWuxing, dayMasterWuxing)) {
        return true;
      }
      return false;
    }

    // 检查是否生助（月支五行生日主五行）
    private isShengZhu(monthWuxing: string, dayMasterWuxing: string): boolean {
      // 更清晰的写法：直接列出相生关系
      const relationships = [
        { from: '木', to: '火' }, // 木生火
        { from: '火', to: '土' }, // 火生土
        { from: '土', to: '金' }, // 土生金  
        { from: '金', to: '水' }, // 金生水
        { from: '水', to: '木' }  // 水生木
      ];
      
      return relationships.some(rel => 
        rel.from === monthWuxing && rel.to === dayMasterWuxing
      );
    }

    /**
     * 获取五行对应的地支
     */
    private getWuxingBranches(wuxing: string): string[] {
      const wuxingBranchesMap = {
        '木': ['寅', '卯'],
        '火': ['巳', '午'],
        '土': ['辰', '戌', '丑', '未'],
        '金': ['申', '酉'],
        '水': ['亥', '子']
      };
      return wuxingBranchesMap[wuxing] || [];
    }

    // 检查破格因素
    private checkBreakFactors(baziData: BaziSystemData, wuxing: string): boolean {
      const allStems = [
        baziData.year.stem,
        baziData.month.stem,
        baziData.day.stem,
        baziData.hour.stem
      ];
      
      // 检查是否有克泄耗
      const keXieHao = this.getKeXieHao(wuxing);
      const hasBreakFactors = allStems.some(stem => {
        const stemWuxing = this.getWuxing(stem);
        return keXieHao.includes(stemWuxing);
      });
      
      return hasBreakFactors;
    }

    // 获取克泄耗
    private getKeXieHao(wuxing: string): string[] {
      const keXieHaoMap = {
        '木': ['金', '火', '土'], // 金克木，火泄木，土耗木
        '火': ['水', '土', '金'], // 水克火，土泄火，金耗火  
        '土': ['木', '金', '水'], // 木克土，金泄土，水耗土
        '金': ['火', '水', '木'], // 火克金，水泄金，木耗金
        '水': ['土', '木', '火']  // 土克水，木泄水，火耗水
      };
      return keXieHaoMap[wuxing] || [];
    }






    // 判断是否为阴干
    private isYinStem(stem: string): boolean {
      const yinStems = ['乙', '丁', '己', '辛', '癸'];
      return yinStems.includes(stem);
    }

    // 判断是否为阳干
    private isYangStem(stem: string): boolean {
      const yangStems = ['甲', '丙', '戊', '庚', '壬'];
      return yangStems.includes(stem);
    }

    // 获取十神的力量权重（符合传统八字理论）
    private getTenStarPower(tenStar: string): number {
      const powerMap: Record<string, number> = {
        // 生扶类（正值）
        '正印': 1.2,   // 生身有情，力量最强
        '偏印': 0.8,   // 生身无情，力量较弱
        '比肩': 1.0,   // 同气相助，力量中等
        '劫财': 0.9,   // 虽帮身但夺财，力量偏弱
        
        // 克泄耗类（负值）
        '七杀': -1.2,  // 克身无情，危害最大
        '正官': -0.8,  // 克身有情，危害较小
        '伤官': -1.1,  // 泄身太过，危害大
        '食神': -0.8,  // 泄身有情，危害小
        '偏财': -1.0,  // 耗身，危害中等
        '正财': -1.0   // 耗身，危害中等
      };
      
      return powerMap[tenStar] || 0; // 未知十神返回0（中性）
    }

    // 获取天干宫位权重（月令最重）
    private getTianganPositionWeight(index: number): number {
      // index: 0=年干, 1=月干, 2=时干
      const weights = [1.0, 1.5, 1.0]; // 月干权重1.5，体现"月令当权"
      return weights[index] || 1.0;
    }

    // 计算日主三要素力量分数（核心计算方法）
    // 返回 { delingScore, dediScore, deshiScore, totalScore }
    private calculateStrengthScores(baziData: BaziSystemData): {
      delingScore: number;
      dediScore: number;
      deshiScore: number;
      totalScore: number;
    } {
      const dayMaster = baziData.day.stem;
      const dayMasterWuxing = this.getWuxing(dayMaster);
      const monthBranch = baziData.month.branch;
      
      // 1. 判断是否得令（二元判断：50分或0分）
      const isDeling = this.checkDeling(baziData);
      const delingScore = isDeling ? 50 : 0;
      
      // 2. 计算得地强度（0-30分）- 考虑藏干深度
      let dediScore = 0;
      
      // 遍历四柱地支，计算根基强度
      const pillars = [
        { branch: baziData.year.branch, zanggan: baziData.year.zanggan, name: '年支' },
        { branch: baziData.month.branch, zanggan: baziData.month.zanggan, name: '月支' },
        { branch: baziData.day.branch, zanggan: baziData.day.zanggan, name: '日支' },
        { branch: baziData.hour.branch, zanggan: baziData.hour.zanggan, name: '时支' }
      ];
      
      pillars.forEach(pillar => {
        const branchWuxing = this.getBranchWuxing(pillar.branch);
        
        // 1. 地支本体五行与日主相同（地支本气通根）
        if (branchWuxing === dayMasterWuxing) {
          dediScore += 10; // 地支本气通根，满分
        }
        // 2. 地支本体五行生助日主（地支本气印星）
        else if (this.isShengZhu(branchWuxing, dayMasterWuxing)) {
          dediScore += 8; // 地支本气印星
        }
        // 3. 地支藏干中有日主同类或印星（根据深度给分）
        else {
          pillar.zanggan.forEach(zanggan => {
            const zangganWuxing = this.getWuxing(zanggan.stem);
            
            // 藏干与日主同类（藏干通根）
            if (zangganWuxing === dayMasterWuxing) {
              if (zanggan.type === '本气') dediScore += 8;
              else if (zanggan.type === '中气') dediScore += 5;
              else if (zanggan.type === '余气') dediScore += 2;
            }
            // 藏干为印星（藏干印星）
            else if (this.isShengZhu(zangganWuxing, dayMasterWuxing)) {
              if (zanggan.type === '本气') dediScore += 6;
              else if (zanggan.type === '中气') dediScore += 4;
              else if (zanggan.type === '余气') dediScore += 1;
            }
          });
        }
      });
      
      // 限制最大值为30
      if (dediScore > 30) dediScore = 30;
      
      // 3. 计算得势强度（0-20分）- 使用加权比例法（考虑十神力量差异 + 宫位权重）
      // 统计生扶力量（比劫、印星）- 直接使用数据中的十神信息
      const tianganStems = [
        { tenStar: baziData.year.tenStar, position: '年干' },
        { tenStar: baziData.month.tenStar, position: '月干' },
        { tenStar: baziData.hour.tenStar, position: '时干' }
      ];
      
      // 计算加权力量分数
      let shengFuPower = 0; // 生扶总力量
      let keXieHaoPower = 0; // 克泄耗总力量
      
      tianganStems.forEach((stem, index) => {
        // 获取宫位权重（年1.0、月1.5、时1.0）
        const positionWeight = this.getTianganPositionWeight(index);
        
        // 获取十神本身的力量权重
        const tenStarPower = this.getTenStarPower(stem.tenStar);
        
        // 综合力量 = 十神力量 × 宫位权重
        const combinedPower = tenStarPower * positionWeight;
        
        if (tenStarPower > 0) {
          shengFuPower += combinedPower; // 正值为生扶
        } else if (tenStarPower < 0) {
          keXieHaoPower += Math.abs(combinedPower); // 负值为克泄耗（取绝对值）
        }
      });
      
      // 计算最大可能力量（用于归一化）
      // 假设3个天干都是最强生扶（正印1.2）且都在月位（1.5权重）
      // 最大生扶力量 ≈ 1.2×1.0 + 1.2×1.5 + 1.2×1.0 = 4.2
      // 实际取 (1.0 + 1.5 + 1.0) × 1.2 = 4.2
      const maxPossiblePower = (1.0 + 1.5 + 1.0) * 1.2;
      
      // 使用比例权重法：基于生扶和克泄耗的力量对比
      // 归一化到[0,1]区间，然后映射到[0,20]分
      const normalizedShengFu = shengFuPower / maxPossiblePower;
      const normalizedKeXieHao = keXieHaoPower / maxPossiblePower;
      
      // 得势 = 20 × (生扶力量占比 - 克泄耗力量占比 + 1) / 2
      let deshiScore = 20 * ((normalizedShengFu - normalizedKeXieHao + 1) / 2);
      
      // 限制在0-20分范围内
      deshiScore = Math.max(0, Math.min(20, deshiScore));
      
      const totalScore = delingScore + dediScore + deshiScore;
      
      return {
        delingScore,
        dediScore,
        deshiScore,
        totalScore
      };
    }





    /**
     * 地支五行映射
     */
    private static readonly BRANCH_WUXING_MAP: Record<string, string> = {
        '子': '水', '亥': '水',
        '寅': '木', '卯': '木',
        '巳': '火', '午': '火',
        '申': '金', '酉': '金',
        '辰': '土', '戌': '土', '丑': '土', '未': '土'
      };

    /**
     * 获取地支五行
     */
    private getBranchWuxing(branch: string): string {
      return PatternAnalyzer.BRANCH_WUXING_MAP[branch] || '';
    }


    // 判断地支本体阴阳
    private isYangBranch(branch: string): boolean {
      // 根据干支分析法规则
      const yangBranches = ['子', '寅', '辰', '午', '申', '戌'];
      return yangBranches.includes(branch);
    }

    // 获取日主属性
    private getDayMasterAttribute(dayMaster: string): string {
      const wuxing = this.getWuxing(dayMaster);
      const yinYang = this.isYangStem(dayMaster) ? '阳' : '阴';
      return `${dayMaster}${wuxing}`;
    }


    /**
     * 宫位权重（年月日时）
     * 
     * 传统命理依据：
     * - 《滴天髓》："月令为纲"（月令是八字的核心）
     * - 《渊海子平》："论命以月令为先"
     * - 《子平真诠》："八字用神，专求月令"
     * 
     * 权重设计：
     * - 月令：3.0（最重要，月令为纲）
     * - 日柱：2.0（日主所在，重要性次于月令）
     * - 年时：1.0（基准权重）
     * 
     * 说明：
     * - 月令权重为3，体现"月令为纲"
     * - 不再使用旺衰系数，月令重要性完全通过宫位权重体现
     * - 避免重复调整，保持计算的纯粹性
     */
    private static readonly POSITION_WEIGHTS = [1, 3, 2, 1];

    /**
     * 获取宫位权重（年月日时统一权重）
     * 适用于：天干、藏干
     */
    private getPositionWeight(index: number): number {
      return PatternAnalyzer.POSITION_WEIGHTS[index] || 1;
    }


    /**
     * 季节五行映射（月令地支 -> 五行）
     */
    private static readonly SEASON_WUXING_MAP: Record<string, string> = {
        '寅': '木', '卯': '木', '辰': '土', // 春季
        '巳': '火', '午': '火', '未': '土', // 夏季
        '申': '金', '酉': '金', '戌': '土', // 秋季
        '亥': '水', '子': '水', '丑': '土'  // 冬季
      };

    /**
     * 获取季节五行
     */
    private getSeasonWuxing(monthBranch: string): string | null {
      return PatternAnalyzer.SEASON_WUXING_MAP[monthBranch] || null;
    }

    /**
     * 根据月令五行计算五行旺衰状态
     * @param monthWuxing 月令五行（木、火、土、金、水）
     * @returns 五行旺衰状态对象，格式：{ '木': '旺', '火': '相', '土': '死', '金': '囚', '水': '休' }
     * 
     * 规则说明：
     * - 旺：当令者（月令本身的五行）
     * - 相：我生者（当令五行所生的五行）
     * - 休：生我者（生当令五行的五行）
     * - 囚：我克者（当令五行所克的五行）
     * - 死：克我者（克当令五行的五行）
     * 
     * @example
     * // 月令为火
     * getWuxingWangShuaiByMonthWuxing('火')
     * // 返回: { '木': '休', '火': '旺', '土': '相', '金': '死', '水': '囚' }
     * 
     * // 可以根据需要灵活使用
     * const wangShuai = getWuxingWangShuaiByMonthWuxing('火');
     * console.log(wangShuai['火']); // '旺'
     * console.log(wangShuai['水']); // '囚'
     */
    private getWuxingWangShuaiByMonthWuxing(monthWuxing: string): Record<string, string> {
      // 五行旺衰对照表（固定映射关系）
      const wangShuaiMap: Record<string, Record<string, string>> = {
        '木': { '木': '旺', '火': '相', '水': '休', '金': '囚', '土': '死' },
        '火': { '火': '旺', '土': '相', '木': '休', '水': '囚', '金': '死' },
        '金': { '金': '旺', '水': '相', '土': '休', '火': '囚', '木': '死' },
        '水': { '水': '旺', '木': '相', '金': '休', '土': '囚', '火': '死' },
        '土': { '土': '旺', '金': '相', '火': '休', '木': '囚', '水': '死' }
      };
      
      const statusMap = wangShuaiMap[monthWuxing];
      if (!statusMap) {
        // 如果传入的五行不合法，返回默认状态
        return { '木': '休', '火': '休', '土': '休', '金': '休', '水': '休' };
      }
      
      return statusMap;
    }

    /**
     * 获取得令等级描述（二元判断）
     */
    private getDelingLevel(score: number): string {
      return score === 50 ? '得令' : '失令';
    }

    /**
     * 获取得地等级描述
     */
    private getDediLevel(score: number): string {
      if (score >= 25) return '强得地';
      if (score >= 18) return '得地';
      if (score >= 10) return '弱得地';
      if (score >= 5) return '微得地';
      return '失地';
    }

    /**
     * 获取得势等级描述（0-20分）
     */
    private getDeshiLevel(score: number): string {
      if (score >= 16) return '强得势';
      if (score >= 12) return '得势';
      if (score >= 8) return '弱得势';
      if (score >= 4) return '微得势';
      return '失势';
    }

    /**
     * 计算日元旺衰状态
     * 权重分配：得令50% + 得地30% + 得势20% = 100%
     */
    private calculateDayMasterStrength(baziData: BaziSystemData): {
      strength: string;
      reasoning: string[];
    } {
      const reasoning: string[] = [];
      
      // 计算三要素力量分数
      const scores = this.calculateStrengthScores(baziData);
      const { delingScore, dediScore, deshiScore, totalScore } = scores;
      
      // 记录三要素得分
      reasoning.push(`第一步：看月令 - 得令强度 ${delingScore}/50 分（${this.getDelingLevel(delingScore)}）`);
      reasoning.push(`第二步：看地支 - 得地强度 ${dediScore}/30 分（${this.getDediLevel(dediScore)}）`);
      reasoning.push(`第三步：看天干 - 得势强度 ${deshiScore}/20 分（${this.getDeshiLevel(deshiScore)}）`);
      reasoning.push(`综合力量评分：${delingScore} + ${dediScore} + ${deshiScore} = ${totalScore.toFixed(0)} 分`);
      
      // 基于总分判断旺衰
      let strength: string;
      
      if (totalScore >= 85) {
        strength = DAY_MASTER_STRENGTH.JI_WANG;
        reasoning.push(`综合判断：总分${totalScore.toFixed(0)}分，力量极强，日元${strength}`);
      } 
      else if (totalScore >= 70) {
        strength = DAY_MASTER_STRENGTH.SHEN_QIANG;
        reasoning.push(`综合判断：总分${totalScore.toFixed(0)}分，日元${strength}`);
      } 
      else if (totalScore >= 55) {
        strength = DAY_MASTER_STRENGTH.PIAN_QIANG;
        reasoning.push(`综合判断：总分${totalScore.toFixed(0)}分，日元${strength}`);
      } 
      else if (totalScore >= 40) {
        strength = DAY_MASTER_STRENGTH.PING_HE;
        reasoning.push(`综合判断：总分${totalScore.toFixed(0)}分，日元${strength}`);
      } 
      else if (totalScore >= 25) {
        strength = DAY_MASTER_STRENGTH.PIAN_RUO;
        reasoning.push(`综合判断：总分${totalScore.toFixed(0)}分，日元${strength}`);
      } 
      else if (totalScore >= 10) {
        strength = DAY_MASTER_STRENGTH.SHEN_RUO;
        reasoning.push(`综合判断：总分${totalScore.toFixed(0)}分，日元${strength}`);
      } 
      else {
        strength = DAY_MASTER_STRENGTH.JI_RUO;
        reasoning.push(`综合判断：总分${totalScore.toFixed(0)}分，力量极弱，日元${strength}`);
      }
      
      return { strength, reasoning };
    }

    // 检查格局稳定性
    private checkPatternStability(baziData: BaziSystemData, pattern: string): {
      hasBreakFactors: boolean;
      breakReasons: string[];
    } {
      const breakReasons: string[] = [];
      const dayMaster = baziData.day.stem;
      const dayMasterWuxing = this.getWuxing(dayMaster);
      
      // 1. 检查是否有冲克破格
      const hasChongKe = this.checkChongKe(baziData, pattern);
      if (hasChongKe.length > 0) {
        breakReasons.push(...hasChongKe);
      }
      
      // 2. 检查是否有混杂破格
      const hasHunZa = this.checkHunZa(baziData, pattern);
      if (hasHunZa.length > 0) {
        breakReasons.push(...hasHunZa);
      }
      
      // 3. 检查刑害破格
      const hasXingHai = this.checkXingHai(baziData, pattern);
      if (hasXingHai.length > 0) {
        breakReasons.push(...hasXingHai);
      }
      
      return {
        hasBreakFactors: breakReasons.length > 0,
        breakReasons
      };
    }

    // 检查冲克破格
    private checkChongKe(baziData: BaziSystemData, pattern: string): string[] {
      const reasons: string[] = [];
      const branches = [
        baziData.year.branch,
        baziData.month.branch,
        baziData.day.branch,
        baziData.hour.branch
      ];
      
      // 检查地支六冲
      const liuChong = [
        ['子', '午'], ['丑', '未'], ['寅', '申'],
        ['卯', '酉'], ['辰', '戌'], ['巳', '亥']
      ];
      
      for (const [branch1, branch2] of liuChong) {
        if (branches.includes(branch1) && branches.includes(branch2)) {
          reasons.push(`地支${branch1}${branch2}相冲，破格`);
        }
      }
      
      return reasons;
    }

    // 检查混杂破格
    private checkHunZa(baziData: BaziSystemData, pattern: string): string[] {
      const reasons: string[] = [];
      
      // 直接使用数据中已经计算好的十神关系
      const tenStars = [
        baziData.year.tenStar,
        baziData.month.tenStar,
        baziData.hour.tenStar
      ];
      
      // 检查正偏混杂
      const zhengPianPairs = [
        ['正官', '七杀'],
        ['正财', '偏财'],
        ['正印', '偏印']
      ];
      
      const tenStarCount: Record<string, number> = {};
      
      tenStars.forEach(tenStar => {
        tenStarCount[tenStar] = (tenStarCount[tenStar] || 0) + 1;
      });
      
      // 检查是否有正偏混杂
      for (const [zheng, pian] of zhengPianPairs) {
        if (tenStarCount[zheng] > 0 && tenStarCount[pian] > 0) {
          reasons.push(`${zheng}${pian}混杂，格局不纯`);
        }
      }
      
      return reasons;
    }


    // 检查刑害破格
    private checkXingHai(baziData: BaziSystemData, pattern: string): string[] {
      const reasons: string[] = [];
      const branches = [
        baziData.year.branch,
        baziData.month.branch,
        baziData.day.branch,
        baziData.hour.branch
      ];
      
      // 检查地支三刑
      const sanXing = [
        ['寅', '巳', '申'], // 无恩之刑
        ['丑', '戌', '未'], // 持势之刑
        ['子', '卯']        // 无礼之刑
      ];
      
      for (const xingGroup of sanXing) {
        if (xingGroup.length === 3) {
          // 三刑
          if (xingGroup.every(branch => branches.includes(branch))) {
            reasons.push(`地支${xingGroup.join('')}构成三刑，破格`);
          }
        } else if (xingGroup.length === 2) {
          // 二刑
          if (xingGroup.every(branch => branches.includes(branch))) {
            reasons.push(`地支${xingGroup.join('')}构成二刑，破格`);
          }
        }
      }
      
      // 检查地支六害
      const liuHai = [
        ['子', '未'], ['丑', '午'], ['寅', '巳'],
        ['卯', '辰'], ['申', '亥'], ['酉', '戌']
      ];
      
      for (const [branch1, branch2] of liuHai) {
        if (branches.includes(branch1) && branches.includes(branch2)) {
          reasons.push(`地支${branch1}${branch2}相害，破格`);
        }
      }
      
      return reasons;
    }


    // 检查是否为建禄格或羊刃格
    private checkSpecialPattern(dayMaster: string, monthBranch: string): string | null {
      // 建禄格：日主在月支处于"临官"位置
      const jianluPatterns: Record<string, Record<string, string>> = {
        '甲': {寅: '建禄格'},
        '乙': {卯: '建禄格'},
        '丙': {巳: '建禄格'},
        '丁': {午: '建禄格'},
        '戊': {巳: '建禄格'},
        '己': {午: '建禄格'},
        '庚': {申: '建禄格'},
        '辛': {酉: '建禄格'},
        '壬': {亥: '建禄格'},
        '癸': {子: '建禄格'}
      };

      // 羊刃格：只有阳干才有羊刃，是日主在月支处于"帝旺"位置
      const yangrenPatterns: Record<string, Record<string, string>> = {
        '甲': {卯: '羊刃格'},  // 甲木帝旺在卯
        '丙': {午: '羊刃格'},  // 丙火帝旺在午
        '戊': {午: '羊刃格'},  // 戊土帝旺在午
        '庚': {酉: '羊刃格'},  // 庚金帝旺在酉
        '壬': {子: '羊刃格'}   // 壬水帝旺在子
      };

      // 先检查羊刃格（阳干，优先级更高）
      if (yangrenPatterns[dayMaster]?.[monthBranch]) {
        return yangrenPatterns[dayMaster][monthBranch];
      }

      // 再检查建禄格
      if (jianluPatterns[dayMaster]?.[monthBranch]) {
        return jianluPatterns[dayMaster][monthBranch];
      }
      
      return null;
    }

  
    /**
     * 从八字系统数据分析格局（主入口）
     * 职责：统筹所有分析步骤，扁平化调用，流程清晰
     */
    public analyzePatternFromBaziSystem(baziData: BaziSystemData): {
      pattern: string;
      reasoning: string[];
      dayMasterStrength: string;
      strengthReasoning: string[];
        dayMasterAttribute: string;
      baziString: string;
    } {
      // ==================== 第一步：日元旺衰分析 ====================
      const strengthResult = this.calculateDayMasterStrength(baziData);
      
      // ==================== 第二步：格局分析 ====================
      const patternResult = this.detectPattern(baziData);
      
      
      
      // ==================== 第八步：日主属性 ====================
      const dayMasterAttribute = this.getDayMasterAttribute(baziData.day.stem);
      
      
      
      // ==================== 第十一步：生成八字字符串 ====================
      const baziString = this.generateBaziString(baziData);
      
      // ==================== 最终：组装结果 ====================
      return {
        baziString,
        pattern: patternResult.pattern,
        reasoning: patternResult.reasoning,
        dayMasterStrength: strengthResult.strength,
        strengthReasoning: strengthResult.reasoning,
        dayMasterAttribute
      };
    }

    /**
     * 格局检测（责任链模式 - 按优先级依次检查）
     */
    private detectPattern(baziData: BaziSystemData): {
      pattern: string;
      reasoning: string[];
    } {
      // 定义格局检测器链（按优先级排序）
      const patternDetectors = [
        () => this.detectSanheSanhuiPattern(baziData),    // 1. 三合三会（变格）
        () => this.detectZhuanwangPattern(baziData),      // 2. 专旺格
        () => this.detectSpecialPattern(baziData),        // 3. 特殊格局（建禄、羊刃）
        () => this.detectCongruoPattern(baziData),        // 4. 从弱格
        () => this.detectNormalPattern(baziData)          // 5. 普通格局
      ];
      
      // 依次执行检测器，返回第一个匹配的格局
      for (const detector of patternDetectors) {
        const result = detector();
        if (result) {
          return result;
        }
      }
      
      // 兜底（理论上不会到这里）
      return {
        pattern: '普通格局',
        reasoning: ['未能确定具体格局']
      };
    }

    /**
     * 检测三合三会格局
     */
    private detectSanheSanhuiPattern(baziData: BaziSystemData): {
      pattern: string;
      reasoning: string[];
    } | null {
      const result = this.checkSanheSanhui(baziData);
      return result ? { pattern: result.pattern, reasoning: [result.reasoning] } : null;
    }

    /**
     * 检测专旺格
     */
    private detectZhuanwangPattern(baziData: BaziSystemData): {
      pattern: string;
      reasoning: string[];
    } | null {
      const result = this.checkZhuanwangPattern(baziData);
      return result ? { pattern: result.pattern, reasoning: [result.reasoning] } : null;
    }

    /**
     * 检测特殊格局（建禄格、羊刃格）
     */
    private detectSpecialPattern(baziData: BaziSystemData): {
      pattern: string;
      reasoning: string[];
    } | null {
      const dayMaster = baziData.day.stem;
      const monthBranch = baziData.month.branch;
      const pattern = this.checkSpecialPattern(dayMaster, monthBranch);
      
      return pattern ? {
        pattern,
        reasoning: [`日主${dayMaster}生于${monthBranch}月，符合${pattern}条件`]
      } : null;
    }

    /**
     * 检测从弱格
     */
    private detectCongruoPattern(baziData: BaziSystemData): {
      pattern: string;
      reasoning: string[];
    } | null {
      const result = this.checkCongruoPattern(baziData);
      return result ? { pattern: result.pattern, reasoning: [result.reasoning] } : null;
    }

    /**
     * 检测普通格局（含破格检查）
     */
    private detectNormalPattern(baziData: BaziSystemData): {
      pattern: string;
      reasoning: string[];
    } {
      // 1. 分析基础格局
      const convertedInput = this.convertBaziSystemData(baziData);
      const normalPattern = this.analyzeNormalPattern(convertedInput);
      
      // 2. 检查格局稳定性
      const stabilityCheck = this.checkPatternStability(baziData, normalPattern.pattern);
      
      // 3. 判断是否破格
      if (stabilityCheck.hasBreakFactors) {
        return {
          pattern: `${normalPattern.pattern}（破格）`,
          reasoning: [...normalPattern.reasoning, ...stabilityCheck.breakReasons]
        };
      }
      
      return normalPattern;
    }

    /**
     * 生成八字字符串
     */
    private generateBaziString(baziData: BaziSystemData): string {
      return `${baziData.year.stem}${baziData.year.branch} ${baziData.month.stem}${baziData.month.branch} ${baziData.day.stem}${baziData.day.branch} ${baziData.hour.stem}${baziData.hour.branch}`;
    }

    /**
     * 分析普通格局（基于输入的八字数据）
     * @deprecated 请使用 analyzePatternFromBaziSystem 替代
     * @see analyzePatternFromBaziSystem
     */
    public analyzePattern(input: BaziInput): {
      pattern: string;
      reasoning: string[];
    } {
      return this.analyzeNormalPattern(input);
    }

    /**
     * 分析普通格局（内部实现）
     */
    private analyzeNormalPattern(input: BaziInput): {
      pattern: string;
      reasoning: string[];
    } {
      const { day_master, month_branch_analysis } = input;
      const dayMaster = day_master.heavenly_stem;
      const monthBranch = month_branch_analysis.branch;
      const hiddenStems = month_branch_analysis.hidden_stems;
      
      const reasoning: string[] = [];
      
      // 1. 先检查特殊格局（建禄格、羊刃格）
      const specialPattern = this.checkSpecialPattern(dayMaster, monthBranch);
      if (specialPattern) {
        reasoning.push(`日主${dayMaster}生于${monthBranch}月，符合${specialPattern}条件`);
        return {
          pattern: specialPattern,
          reasoning
        };
      }
      
      // 2. 根据月支类型判断普通格局
      // 子午卯酉：四正，直接以月令主气取格
      const ziWuMaoYou = ['子', '午', '卯', '酉'];
      // 辰戌丑未：四库，杂气格，需要论以月令透干取格
      const chenXuChouWei = ['辰', '戌', '丑', '未'];
      // 寅申巳亥：四长生，普通格，本气透出取格
      const yinShenSiHai = ['寅', '申', '巳', '亥'];
      
      let pattern = '';
      
      // 查找本气
      const mainQi = hiddenStems.find(stem => stem.strength === '本气');
      // 查找透出的天干
      const exposedStems = hiddenStems.filter(stem => stem.is_exposed);
      
      // 月支为"子午卯酉" - 直接以月令主气取格
      if (ziWuMaoYou.includes(monthBranch)) {
        if (mainQi) {
          pattern = PATTERN_NAMES[mainQi.relation] || `${mainQi.relation}格`;
          reasoning.push(`月支${monthBranch}为子午卯酉之一，直接以本气${mainQi.stem}(${mainQi.relation})取格`);
        } else {
          reasoning.push(`月支${monthBranch}为子午卯酉之一，但未找到本气，无法确定格局`);
          pattern = '未知格局';
        }
      }
      // 月支为"辰戌丑未" - 杂气格，需要论以月令透干取格
      else if (chenXuChouWei.includes(monthBranch)) {
        // 按照文档要求的5个步骤取格
        const exposedMainQi = exposedStems.find(stem => stem.strength === '本气');
        const exposedZhongQi = exposedStems.filter(stem => stem.strength === '中气');
        const exposedYuQi = exposedStems.filter(stem => stem.strength === '余气');
        
        // (1) 若月令本气透出天干，应先取为格
        if (exposedMainQi) {
          const patternName = PATTERN_NAMES[exposedMainQi.relation] || `${exposedMainQi.relation}格`;
          pattern = `杂气${patternName}`;
          reasoning.push(`月支${monthBranch}为辰戌丑未之一，本气${exposedMainQi.stem}透出为${exposedMainQi.relation}，取杂气${patternName}`);
        }
        // (2) 若月令本气不透，只透出一个中气或一个余气，应将透出之物取格
        else if (exposedZhongQi.length === 1 && exposedYuQi.length === 0) {
          const exposedStem = exposedZhongQi[0];
          const patternName = PATTERN_NAMES[exposedStem.relation] || `${exposedStem.relation}格`;
          pattern = `杂气${patternName}`;
          reasoning.push(`月支${monthBranch}为辰戌丑未之一，本气不透，中气${exposedStem.stem}透出为${exposedStem.relation}，取杂气${patternName}`);
        }
        else if (exposedYuQi.length === 1 && exposedZhongQi.length === 0) {
          const exposedStem = exposedYuQi[0];
          const patternName = PATTERN_NAMES[exposedStem.relation] || `${exposedStem.relation}格`;
          pattern = `杂气${patternName}`;
          reasoning.push(`月支${monthBranch}为辰戌丑未之一，本气不透，余气${exposedStem.stem}透出为${exposedStem.relation}，取杂气${patternName}`);
        }
        // (3) 若月令本气不透，同时透出中气和余气，则酌取其一为格
        else if (exposedZhongQi.length > 0 && exposedYuQi.length > 0) {
          // 优先取中气，如果中气余气都只有一个，取中气
          if (exposedZhongQi.length === 1 && exposedYuQi.length === 1) {
            const exposedStem = exposedZhongQi[0];
            const patternName = PATTERN_NAMES[exposedStem.relation] || `${exposedStem.relation}格`;
            pattern = `杂气${patternName}`;
            reasoning.push(`月支${monthBranch}为辰戌丑未之一，本气不透，中气余气同透，取中气${exposedStem.stem}(${exposedStem.relation})为格`);
          } else {
            // 如果透出多个，取力量最强的
            const allExposed = [...exposedZhongQi, ...exposedYuQi];
            const strongestStem = allExposed.reduce((prev, current) => 
              current.strength === '本气' ? current : 
              (current.strength === '中气' && prev.strength !== '本气') ? current : prev
            );
            const patternName = PATTERN_NAMES[strongestStem.relation] || `${strongestStem.relation}格`;
            pattern = `杂气${patternName}`;
            reasoning.push(`月支${monthBranch}为辰戌丑未之一，本气不透，多个藏干同透，取力量最强的${strongestStem.stem}(${strongestStem.relation})为格`);
          }
        }
        // (4) 若月令藏干均不透，应取有力而无克合者为格
        else if (exposedStems.length === 0) {
          if (mainQi) {
            const patternName = PATTERN_NAMES[mainQi.relation] || `${mainQi.relation}格`;
            pattern = `杂气${patternName}`;
            reasoning.push(`月支${monthBranch}为辰戌丑未之一，藏干均不透，取本气${mainQi.stem}(${mainQi.relation})为格`);
          } else {
            reasoning.push(`月支${monthBranch}为辰戌丑未之一，但未找到本气，无法确定格局`);
            pattern = '未知格局';
          }
        }
        // (5) 若月令构成了三合三会局，优先取三合三会之物为格
        // 这个逻辑在checkSanheSanhui中已经处理，会优先返回
      }
      // 月支为"寅申巳亥" - 普通格
      else if (yinShenSiHai.includes(monthBranch)) {
        const exposedMainQi = exposedStems.find(stem => stem.strength === '本气');
        
        if (exposedMainQi) {
          // 月令本气透出
          pattern = PATTERN_NAMES[exposedMainQi.relation] || `${exposedMainQi.relation}格`;
          reasoning.push(`月支${monthBranch}为寅申巳亥之一，本气${exposedMainQi.stem}透出为${exposedMainQi.relation}`);
        } else {
          // 本气不透，取本气为格
          if (mainQi) {
            pattern = PATTERN_NAMES[mainQi.relation] || `${mainQi.relation}格`;
            reasoning.push(`月支${monthBranch}为寅申巳亥之一，本气未透，取本气${mainQi.stem}(${mainQi.relation})为格`);
          } else {
            reasoning.push(`月支${monthBranch}为寅申巳亥之一，但未找到本气，无法确定格局`);
            pattern = '未知格局';
          }
        }
      }
      // 其他月支（理论上不应该到达这里）
      else {
        reasoning.push(`月支${monthBranch}不在标准分类中，无法确定格局`);
        pattern = '未知格局';
      }
      
      return {
        pattern,
        reasoning
      };
    }
  }
  
  
  // 导出类和类型
  export { PatternAnalyzer, BaziSystemData, BaziInput, PatternHiddenStem, BaziSystemHiddenStem, MonthBranchAnalysis, BaziData, DayMaster };
  